From 9081e301d43a9090582cdb4cf5c562253469c79063bec234411493d363a3647c Mon Sep 17 00:00:00 2001 From: Kira Date: Wed, 6 May 2026 23:21:12 +0200 Subject: [PATCH] More work on keyboard stage, now compiling. --- src/locales/en.json | 7 +- src/stages/keyboard/mod.rs | 168 ++++++++++++++++++++----------------- 2 files changed, 97 insertions(+), 78 deletions(-) diff --git a/src/locales/en.json b/src/locales/en.json index 7e915fe..9d98825 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -22,6 +22,9 @@ "timezone.select_timezone": "Please select preffered time zone", "timezone.init_error": "Error getting time zones data from system!", "locale.select_language_locale": "The system language will be set to", - "locale.select_formats_locale": "The numbers and dates locale will be set to" - + "locale.select_formats_locale": "The numbers and dates locale will be set to", + "keyboard.select_model": "Select keyboard model", + "keyboard.select_layout": "Select keyboard layout", + "keyboard.select_variant": "Select keyboard variant", + "keyboard.init_error": "Error getting keyboard layouts information from the system!" } \ No newline at end of file diff --git a/src/stages/keyboard/mod.rs b/src/stages/keyboard/mod.rs index f979f37..e7a15af 100644 --- a/src/stages/keyboard/mod.rs +++ b/src/stages/keyboard/mod.rs @@ -29,7 +29,11 @@ pub struct Layout { layout: String, description: String, } - +impl std::fmt::Display for Layout { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{} ({})", &self.layout, &self.description) + } +} impl Layout { pub fn from_str_touple(v: &(&str, &str)) -> Self { Self { @@ -39,12 +43,17 @@ impl Layout { } } + #[derive(Debug, Clone, PartialEq, Eq)] pub struct Variant { variant: String, description: String, } - +impl std::fmt::Display for Variant { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{} ({})", &self.variant, &self.description) + } +} impl Variant { pub fn from_str_touple(v: &(&str, &str)) -> Self { Self { @@ -60,11 +69,24 @@ pub struct KeyboarLayout { variant: Variant, } +impl KeyboarLayout { + pub fn to_result(&self) -> String { + format!("{}||{}", self.layout.layout, self.variant.variant) + } + +} + #[derive(Debug, Clone, PartialEq, Eq)] pub struct KeyboarModel { model: String, description: String, } +impl std::fmt::Display for KeyboarModel { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + write!(f, "{} ({})", &self.model, &self.description) + } +} + impl KeyboarModel { pub fn from_str_touple(v: &(&str, &str)) -> Self { Self { @@ -74,7 +96,6 @@ impl KeyboarModel { } } - impl std::fmt::Display for KeyboarLayout { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}/{}", &self.layout.layout, &self.variant.variant) @@ -86,17 +107,17 @@ pub struct KeyboardStage { models: Vec, layouts: Vec, variants_map: HashMap>, - variants: Vec, + variants: Vec, model: Option, - layout: Option, - variant: Option, + layout: Option, + variant: Option, keyboard_layouts: Vec, selected_kbd_layout_id: Option, } #[derive(Debug, Clone)] pub enum Message { - SelectKeyboardModel(kira_scroll_list::ListViewMessage), + SelectKeyboardModel(KeyboarModel), SelectLayout(kira_scroll_list::ListViewMessage), SelectVariant(kira_scroll_list::ListViewMessage), @@ -111,7 +132,11 @@ pub enum Message { const XKB_RULES_FILE_NAME: &str = "/usr/share/X11/xkb/rules/evdev.lst"; /// Getting list of awailable keyboard layouts from from xkb/rules/evdev.lst file. -fn get_layouts_blocking() -> std::io::Result<(Vec, Vec, HashMap>)> { +fn get_layouts_blocking() -> std::io::Result<( + Vec, + Vec, + HashMap>, +)> { use std::fs::File; use std::io::{BufReader, Read}; @@ -124,7 +149,6 @@ fn get_layouts_blocking() -> std::io::Result<(Vec, Vec, Ha let raw_sections: Vec = file_content.split("! ").map(str::to_string).collect(); - // Parsing models data let models: Vec = raw_sections .iter() @@ -177,9 +201,9 @@ fn get_layouts_blocking() -> std::io::Result<(Vec, Vec, Ha .for_each(|v| { let maybe_key = variants .get_mut(v.0) - .and_then(|vrn_vec| Some(vrn_vec.push(v.1))); + .and_then(|vrn_vec| Some(vrn_vec.push(v.1.clone()))); if maybe_key.is_none() { - variants.insert(v.0.to_string(), vec![v.1]); + variants.insert(v.0.to_string(), vec![v.1.clone()]); } }), ) @@ -191,23 +215,30 @@ fn get_layouts_blocking() -> std::io::Result<(Vec, Vec, Ha impl KeyboardStage { pub fn new() -> Result { match get_layouts_blocking() { - Ok((models, layouts, variants)) => { - + Ok((models, layouts, variants_map)) => Ok({ + let def_layout = layouts + .iter() + .enumerate() + .find_map(|(idx, l)| (l.layout == "us").then_some(idx)); + let variants = variants_map + .get("us") + .cloned() + .unwrap_or_else(|| Vec::new()); - Ok(Self { - - layouts: layouts, - variants_map: variants, - variants: Vec::new(), - model: Some(models[0].clone()), - models: models, - layout: None, - variant: None, - keyboard_layouts: Vec::new(), - selected_kbd_layout_id: None, + let def_model = models[0].clone(); + + Self { + layouts: layouts, + variants_map: variants_map, + variants: variants, + model: Some(def_model), + models: models, + layout: def_layout, + variant: Some(0), + keyboard_layouts: Vec::new(), + selected_kbd_layout_id: None, } - ) - } + }), Err(ex) => { let err = format!( "Exception while trying to get kayboard layouts data from system {}", @@ -219,95 +250,80 @@ impl KeyboardStage { } fn gen_result(&self) -> StageResult { - if let Some(time_zone) = &self.selected_zone { + if let Some(model) = &self.model && self.keyboard_layouts.len() > 0 { StageResult { - name: "time_zone".to_string(), + name: "keyboard".to_string(), config: Some(HashMap::from([ ( - "name".to_string(), - ConfigValue::String(time_zone.to_string()), + "model".to_string(), + ConfigValue::String(model.model.clone()), ), ( - "region".to_string(), - ConfigValue::String(time_zone.region.clone()), - ), - ( - "zone".to_string(), - ConfigValue::String(time_zone.zone.clone()), + "layouts".to_string(), + ConfigValue::Vector(self.keyboard_layouts.iter().map(|kl| ConfigValue::String(kl.to_result())).collect()), ), ])), resuts: None, error: None, } - } else { + } + else { StageResult { - name: "time_zone".to_string(), + name: "keyboard".to_string(), config: None, resuts: None, - error: None, + error: Some("Something go terrible wrong, there is no keyboard layouts.".into()), } } } pub fn update(&mut self, message: Message) -> StageAction { match message { - Message::SelectRegion(scroll_list::ListViewMessage::Select(region_id)) => { - let region = self.regions.get(region_id).unwrap(); - self.zones = self - .time_zones - .as_ref() - .unwrap() - .get(region) - .unwrap() - .clone(); - self.region_id = Some(region_id); - self.zone_id = None; - //self.selected_zone_text.clear(); - StageAction::None - } - Message::SelectZone(scroll_list::ListViewMessage::Select(zone_id)) => { - let zone = TimeZoneData { - region: self.regions[self.region_id.unwrap()].clone(), - zone: self.zones[zone_id].clone(), - }; - self.selected_zone_text = - format!("{} {}", t!("timezone.selected_timezone"), zone.to_string()); - self.zone_id = Some(zone_id); - self.selected_zone = Some(zone); - StageAction::None - } Message::Next => StageAction::Next(self.gen_result()), Message::Back => StageAction::Back, + _ => StageAction::None, } } pub fn view(&self) -> iced::Element<'_, Message> { - let next_button = if self.zone_id.is_some() { + + let next_button = if self.model.is_some() && self.keyboard_layouts.len() > 0 { widget::button(widget::text(t!("button.next"))).on_press(Message::Next) } else { widget::button(widget::text(t!("button.next"))) }; - let main_content = match &self.time_zones { - Ok(_) => widget::container( + + let main_content = if self.layouts.len() > 0 { + widget::container( widget::column![ - widget::text(t!("timezone.select_timezone")), + widget::text(t!("keyboard.select_model")), + widget::pick_list( + self.models.clone(), + self.model.clone(), + Message::SelectKeyboardModel, + ), widget::row![ - scroll_list::list_view(&self.regions, self.region_id, Length::Shrink) - .map(Message::SelectRegion), - scroll_list::list_view(&self.zones, self.zone_id, Length::FillPortion(1)) - .map(Message::SelectZone), + widget::column![ + widget::text(t!("keyboard.select_layout")), + crate::kira_scroll_list::list_view(&self.layouts, self.layout, Length::Shrink) + .map(Message::SelectLayout)], + + widget::column![ + widget::text(t!("keyboard.select_variant")), + crate::kira_scroll_list::list_view(&self.variants, self.variant, Length::FillPortion(1)) + .map(Message::SelectVariant)], ] .padding(20) .spacing(10) .height(Length::Shrink), - widget::text(self.selected_zone_text.clone()) ] .spacing(10) .align_x(Alignment::Center), - ), + )} + else { + widget::container(widget::text(t!("keyboard.init_error"))) + }; - Err(_) => widget::container(widget::text(t!("timezone.init_error"))), - }; let back_button = widget::button(widget::text(t!("button.back"))).on_press(Message::Back); widget::column![